package store.lunangangster.engine.impl.cmd;

import java.util.Map;
import store.lunangangster.engine.NodeFlowIllegalArgumentException;
import store.lunangangster.engine.NodeFlowObjectNotFoundException;
import store.lunangangster.engine.impl.entity.mgr.DeploymentManager;
import store.lunangangster.engine.impl.helper.ProcessInstanceHelper;
import store.lunangangster.engine.impl.interceptor.CommandContext;
import store.lunangangster.engine.impl.runtime.ProcessInstance;
import store.lunangangster.engine.repository.ProcessDefinition;

/**
 * 启动一个已经部署的ProcessDefinition
 *
 * @author cwk
 * @version 1.0
 */
public class StartProcessCmd implements Command<ProcessInstance> {

  protected String processInstanceName;
  protected String processDefinitionId;
  protected String processDefinitionKey;
  protected Map<String, Object> variables;

  public StartProcessCmd(String processDefinitionId, String processDefinitionKey) {
    this(null, processDefinitionId, processDefinitionKey, null);
  }

  public StartProcessCmd(String processInstanceName, String processDefinitionId, String processDefinitionKey) {
    this(processInstanceName, processDefinitionId, processDefinitionKey, null);
  }

  public StartProcessCmd(String processInstanceName, String processDefinitionId, String processDefinitionKey,
      Map<String, Object> variables) {
    this.processInstanceName = processInstanceName;
    this.processDefinitionId = processDefinitionId;
    this.processDefinitionKey = processDefinitionKey;
    this.variables = variables;
  }

  @Override
  public ProcessInstance execute(CommandContext commandContext) {
    DeploymentManager deploymentManager = commandContext.getProcessEngineConfiguration()
        .getDeploymentManager();

    // find ProcessDefinition
    ProcessDefinition processDefinition;
    if (processDefinitionId != null) {
       processDefinition = deploymentManager.findProcessDefinitionById(processDefinitionId);
       if (processDefinition == null) {
         throw new NodeFlowObjectNotFoundException("No process definition found for id = \"" + processDefinitionId + "\"", ProcessDefinition.class);
       }
    } else if (processDefinitionKey != null) {
       processDefinition = deploymentManager.findProcessDefinitionByKey(processDefinitionKey);
      if (processDefinition == null) {
        throw new NodeFlowObjectNotFoundException("No process definition found for key = \"" + processDefinitionKey + "\"", ProcessDefinition.class);
      }
    } else {
      throw new NodeFlowIllegalArgumentException("The id and key of process definition are null");
    }
    ProcessInstanceHelper processInstanceHelper
        = commandContext.getProcessEngineConfiguration().getProcessInstanceHelper();
    return processInstanceHelper.createProcessInstanceAndStart(processDefinition,
        processInstanceName, variables);
  }
}
